home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-06-30 | 15.6 KB | 520 lines |
- /*
- * @(#)LargeTreeModelNode.java 1.7 98/02/02
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-
- package com.sun.java.swing.plaf.basic;
-
- import com.sun.java.swing.tree.DefaultMutableTreeNode;
- import com.sun.java.swing.tree.TreePath;
- import com.sun.java.swing.tree.TreeModel;
- import com.sun.java.swing.tree.TreeSelectionModel;
-
- /**
- * LargeTreeModelNode is used by AbstractTreeUI to track what has been
- * expanded. LargeTreeModelNode differs from VisibleTreeNode in that it
- * is highly model intensive. That is almost all queries to a
- * LargeTreeModelNode result in the TreeModel being queried. It also
- * will not support odd sized row heights.
- * <p>
- * Warning: serialized objects of this class will not be compatible with
- * future swing releases. The current serialization support is appropriate
- * for short term storage or RMI between Swing1.0 applications. It will
- * not be possible to load serialized Swing1.0 objects with future releases
- * of Swing. The JDK1.2 release of Swing will be the compatibility
- * baseline for the serialized form of Swing objects.
- *
- * @version 1.7 02/02/98
- * @author Scott Violet
- */
- public class LargeTreeModelNode extends DefaultMutableTreeNode {
- /** Tree UI this is created for. */
- protected AbstractTreeUI treeUI;
-
- /** Is this node expanded? */
- protected boolean isExpanded;
-
- /** Index of this node from the model. */
- protected int childIndex;
-
- public LargeTreeModelNode(AbstractTreeUI treeUI, Object userObject,
- int childIndex) {
- super(userObject);
- this.treeUI = treeUI;
- this.childIndex = childIndex;
- }
-
- /**
- * Returns the model for the current tree.
- */
- public TreeModel getModel() {
- return treeUI.getModel();
- }
-
- /**
- * Returns the index of the reciever in the model.
- */
- public int getChildIndex() {
- return childIndex;
- }
-
- /**
- * Returns the child for the passed in model index.
- */
- public LargeTreeModelNode childAtModelIndex(int index) {
- for(int counter = getChildCount() - 1; counter >= 0; counter--)
- if(((LargeTreeModelNode)getChildAt(counter)).childIndex == index)
- return (LargeTreeModelNode)getChildAt(counter);
- return null;
- }
-
- /**
- * Returns true if this node is visible. This is determined by
- * asking all the parents if they are expanded.
- */
- public boolean isVisible() {
- LargeTreeModelNode parent = (LargeTreeModelNode)getParent();
-
- if(parent == null)
- return true;
- return (parent.isExpanded() && parent.isVisible());
- }
-
- /**
- * Returns the row of the receiver.
- */
- public int getRow() {
- LargeTreeModelNode parent = (LargeTreeModelNode)getParent();
-
- if(parent == null) {
- if(treeUI.isRootVisible())
- return 0;
- return -1;
- }
- return parent.getCountTo(childIndex);
- }
-
- /**
- * Expands the receiver. If adjustTree is true didAdjustTree and
- * visibleNodesChanged is messaged.
- */
- public void expand(boolean adjustTree) {
- if(!isExpanded) {
- boolean visible = isVisible();
-
- isExpanded = true;
- if(visible)
- adjustLargeRowCountBy(getTotalChildCount());
- if(adjustTree) {
- didAdjustTree();
- treeUI.visibleNodesChanged();
- }
- treeUI.pathWasExpanded(new TreePath(getUserObjectPath()));
-
- /* Update the selection model, and the selected entries if
- the receivers row and the row after it are selected. */
- if(treeUI != null && visible) {
- int cCount;
- int row = getRow();
- TreeSelectionModel selModel = treeUI.getSelectionModel();
-
- if(selModel != null && (cCount = getTotalChildCount()) > 0 &&
- selModel.isRowSelected(row) &&
- selModel.isRowSelected(row + 1)) {
- TreePath[] paths = new TreePath[cCount];
-
- for(int counter = 0; counter < cCount; counter++)
- paths[counter] = treeUI.getPathForRow(counter + row+1);
- selModel.addSelectionPaths(paths);
- }
- else if(selModel != null)
- selModel.resetRowSelection();
- }
- }
- }
-
- /**
- * Collapses the receiver. If <code>adjustTree</code> is true
- * didAdjustTree and pathWasCollapsed are messaged.
- */
- public void collapse(boolean adjustTree) {
- if(isExpanded) {
- TreePath[] selPaths;
- TreeSelectionModel selModel = null;
-
- if(treeUI != null && (selModel = treeUI.getSelectionModel())
- != null)
- selPaths = selModel.getSelectionPaths();
- else
- selPaths = null;
- if(isVisible())
- adjustLargeRowCountBy(-getTotalChildCount());
- isExpanded = false;
- if(adjustTree) {
- didAdjustTree();
- treeUI.visibleNodesChanged();
- }
- treeUI.pathWasCollapsed(new TreePath(getUserObjectPath()));
-
- /* update the selection */
- if(selPaths != null) {
- boolean shouldRemove = false;
- TreePath ourPath = new TreePath(getUserObjectPath());
-
- for(int counter = selPaths.length - 1; counter >= 0;
- counter--) {
- if(selPaths[counter] != null &&
- ourPath.isDescendant(selPaths[counter]) &&
- !ourPath.equals(selPaths[counter]))
- shouldRemove = true;
- else
- selPaths[counter] = null;
- }
- if(shouldRemove)
- selModel.removeSelectionPaths(selPaths);
- }
- }
- }
-
- /**
- * Returns the number of children in the receiver by descending all
- * expanded nodes and messaging them with getTotalChildCount.
- */
- public int getTotalChildCount() {
- if(isExpanded()) {
- int retCount = getModel().getChildCount(getUserObject());
-
- for(int counter = getChildCount() - 1; counter >= 0;
- counter--) {
- retCount += ((LargeTreeModelNode)getChildAt(counter))
- .getTotalChildCount();
- }
- return retCount;
- }
- return 0;
- }
-
- /**
- * Returns true if this node is expanded.
- */
- public boolean isExpanded() {
- return isExpanded;
- }
-
- /**
- * Messaged when the child count has changed and this node hasn't
- * yet been expanded, does nothing.
- */
- public void modelChildCountChanged() {
- }
-
- /**
- * The highest visible nodes have a depth of 0.
- */
- public int getVisibleLevel() {
- if (treeUI.isRootVisible()) {
- return getLevel();
- } else {
- return getLevel()-1;
- }
- }
-
- /**
- * Makes the receiver collapse if it is currently expanded, otherwise
- * expands the reciever.
- */
- public void toggleExpanded() {
- if (isExpanded()) {
- collapse(true);
- } else {
- expand(true);
- }
- }
-
- /**
- * Adjust the large row count of the AbstractTreeUI the receiver was
- * created with.
- */
- protected void adjustLargeRowCountBy(int changeAmount) {
- treeUI.largeRowCount += changeAmount;
- }
-
- /**
- * Adds newChild to this nodes children at the appropriate location.
- * The location is determined from the childIndex of newChild.
- */
- protected void addLargeTreeModelNode(LargeTreeModelNode newChild) {
- boolean added = false;
- int childIndex = newChild.getChildIndex();
-
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- if(((LargeTreeModelNode)getChildAt(counter)).getChildIndex() >
- childIndex) {
- added = true;
- insert(newChild, counter);
- counter = maxCounter;
- }
- }
- if(!added)
- add(newChild);
- }
-
- /**
- * Messaged when a child has been removed from the model at the
- * specified index. Will shift down all the childIndexs that
- * are >= index.
- */
- protected void childRemovedAtModelIndex(int index) {
- LargeTreeModelNode aChild;
-
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- aChild = (LargeTreeModelNode)getChildAt(counter);
- if(aChild.childIndex >= index) {
- /* Since matched and children are always sorted by
- index, no need to continue testing with the above. */
- for(; counter < maxCounter; counter++)
- ((LargeTreeModelNode)getChildAt(counter)).childIndex--;
- }
- }
- }
-
- /**
- * Messaged when a child has been inserted at index. For all the
- * children that have a childIndex >= index their index is incremented
- * by one.
- */
- protected void childInsertedAtModelIndex(int index) {
- LargeTreeModelNode aChild;
-
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- aChild = (LargeTreeModelNode)getChildAt(counter);
- if(aChild.childIndex >= index) {
- /* Since matched and children are always sorted by
- index, no need to continue testing with the above. */
- for(; counter < maxCounter; counter++)
- ((LargeTreeModelNode)getChildAt(counter)).childIndex++;
- }
- }
- }
-
- /**
- * Returns the TreePath for the given row. This will return null
- * if the row is greater than the number of expanded nodes.<p>
- * rowCounter is used to count the number of nodes while descending
- * the hierarchy. <p>
- * If eNode is non-null then eNode will be set to either the matching
- * node, or its parent if the last element has not yet been
- * expanded, or is a leaf.<p>
- * isParentNode will be set to true if the parent is set in
- * eNode, otherwise false.<p>
- * The TreePath will be returned in retPath (if it is non-null)
- * Returns the child index of the returned row in childIndex (if
- * non-null).<p>
- * The reason for all these arguments is different methods call
- * this with different requirements and rather than having 4
- * different methods, there is one big one.<p>
- * If no match is found, false is returned, otherwise true.
- */
- protected boolean getPathForRow(int row, int[] rowCounter,
- TreePath[] retPath,
- LargeTreeModelNode[] eNode,
- boolean[] isParentNode,
- int[] childIndex) {
- if(row == rowCounter[0]) {
- if(childIndex != null)
- childIndex[0] = getChildIndex();
- if(eNode != null) {
- eNode[0] = this;
- isParentNode[0] = false;
- }
- if(retPath != null)
- retPath[0] = new TreePath(getUserObjectPath());
- return true;
- }
- rowCounter[0]++;
- if(isExpanded) {
- LargeTreeModelNode aNode;
- int endIndex;
- int lastChildIndex = 0;
- int newChildIndex;
- TreeModel treeModel = getModel();
-
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- aNode = (LargeTreeModelNode)getChildAt(counter);
- newChildIndex = aNode.childIndex;
- if((rowCounter[0] + (newChildIndex - lastChildIndex)) >
- row) {
- if(childIndex != null)
- childIndex[0] = row - rowCounter[0] +
- lastChildIndex;
- if(retPath != null) {
- Object child;
- Object[] thisPath = getUserObjectPath();
- int pLength = thisPath.length;
- Object[] newPath = new Object[pLength + 1];
-
- child = treeModel.getChild(userObject,
- (row - rowCounter[0] + lastChildIndex));
- System.arraycopy(thisPath, 0, newPath, 0, pLength);
- newPath[pLength] = child;
- retPath[0] = new TreePath(newPath);
- }
- if(eNode != null) {
- eNode[0] = this;
- isParentNode[0] = true;
- }
- return true;
- }
- rowCounter[0] += (newChildIndex - lastChildIndex);
- lastChildIndex = newChildIndex + 1;
- if(aNode.getPathForRow(row, rowCounter, retPath, eNode,
- isParentNode, childIndex)) {
- return true;
- }
- }
- newChildIndex = treeModel.getChildCount(userObject) - 1;
- if((newChildIndex - lastChildIndex) >= 0) {
- if((rowCounter[0] + (newChildIndex - lastChildIndex))
- >= row) {
- Object child;
-
- if(childIndex != null)
- childIndex[0] = row - rowCounter[0] +
- lastChildIndex;
- if(retPath != null) {
- Object[] thisPath = getUserObjectPath();
- int pLength = thisPath.length;
- Object[] newPath = new Object[pLength + 1];
-
- child = treeModel.getChild(userObject,
- (row - rowCounter[0] + lastChildIndex));
- System.arraycopy(thisPath, 0, newPath, 0, pLength);
- newPath[pLength] = child;
- retPath[0] = new TreePath(newPath);
- }
- if(eNode != null) {
- eNode[0] = this;
- isParentNode[0] = true;
- }
- return true;
- }
- rowCounter[0] += (newChildIndex - lastChildIndex) + 1;
- }
- }
- return false;
- }
-
- /**
- * Asks all the children of the receiver for their totalChildCount
- * and returns this value (plus stopIndex).
- */
- protected int getCountTo(int stopIndex) {
- LargeTreeModelNode aChild;
- int retCount = stopIndex + 1;
-
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- aChild = (LargeTreeModelNode)getChildAt(counter);
- if(aChild.childIndex >= stopIndex)
- counter = maxCounter;
- else
- retCount += aChild.getTotalChildCount();
- }
- if(parent != null)
- return retCount + ((LargeTreeModelNode)getParent())
- .getCountTo(childIndex);
- if(!treeUI.isRootVisible())
- return (retCount - 1);
- return retCount;
- }
-
- /**
- * Returns, by reference in rowCounter, the row for the given
- * path. This is meant to be called from the root, it will not
- * compute the row of the receiver.<p>
- * Path is the path that is being searched for.
- * pathCounter is the current index into path
- * pathLength is the length of the path (avoids path.length);
- * isInPath is true if the parents path is contained in path.
- * returns true if the row is found.
- */
- protected boolean getRow(Object[] path, int pathCounter,
- int pathLength, boolean isInPath,
- int[] rowCounter) {
- isInPath = (isInPath && path[pathCounter].equals(userObject));
- if(isInPath) {
- if(++pathCounter == pathLength)
- return true;
- }
- rowCounter[0]++;
- if(isExpanded) {
- LargeTreeModelNode aNode;
- int endIndex;
- int lastChildIndex;
- int newChildIndex;
- int newRowCount;
- TreeModel treeModel = getModel();
-
- if(isInPath && (pathCounter + 1) == pathLength)
- endIndex = treeModel.getIndexOfChild(userObject,
- path[pathLength - 1]);
- else
- endIndex = Integer.MAX_VALUE;
- lastChildIndex = 0;
- newRowCount = rowCounter[0];
- for(int counter = 0, maxCounter = getChildCount();
- counter < maxCounter; counter++) {
- aNode = (LargeTreeModelNode)getChildAt(counter);
- newChildIndex = aNode.childIndex;
- if(newChildIndex >= endIndex) {
- rowCounter[0] = newRowCount +
- (endIndex - lastChildIndex);
- return true;
- }
- newRowCount += (newChildIndex - lastChildIndex);
- lastChildIndex = newChildIndex + 1;
- rowCounter[0] = newRowCount;
- if(aNode.getRow(path, pathCounter, pathLength,
- isInPath, rowCounter))
- return true;
- newRowCount = rowCounter[0];
- }
- newChildIndex = treeModel.getChildCount(userObject) - 1;
- if(newChildIndex >= 0) {
- if(newChildIndex >= endIndex) {
- rowCounter[0] = newRowCount +
- (endIndex - lastChildIndex);
- return true;
- }
- rowCounter[0] += (newChildIndex - lastChildIndex) + 1;
- }
- }
- return false;
- }
-
- /**
- * Messaged when this node either expands or collapses.
- */
- protected void didAdjustTree() {
- }
- }
-